package com.ecommerce.dao.mybatis.mapper;

import com.ecommerce.product.domain.Product;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * 商品数据访问接口
 * 提供商品基础CRUD及查询操作
 */
@Mapper
public interface ProductMapper {
    /**
     * 插入新商品记录
     *
     * @param product 商品实体对象（必须包含所有非空字段）
     * @return 受影响的行数（1表示插入成功）
     * @throws IllegalArgumentException 当product为null时抛出
     * @since 1.0.0
     */
    int insert(Product product);

    /**
     * 根据主键更新商品信息
     *
     * @param product 商品实体对象（必须包含id和需要更新的字段）
     * @return 受影响的行数（1表示更新成功，0表示记录不存在）
     * @throws IllegalArgumentException 当product为null或id为null时抛出
     * @version 1.1.0 增加乐观锁版本控制支持
     * @since 1.0.0
     */
    int updateById(Product product);

    /**
     * 根据主键删除商品记录（逻辑删除/物理删除）
     *
     * @param id 商品主键ID（必须大于0）
     * @return 受影响的行数（1表示删除成功，0表示记录不存在）
     * @throws IllegalArgumentException 当id为null或<=0时抛出
     * @since 1.0.0
     */
    int deleteById(Long id);

    /**
     * 根据主键查询商品详情
     *
     * @param id 商品主键ID（必须大于0）
     * @return 商品实体对象（未找到时返回null）
     * @throws IllegalArgumentException 当id为null或<=0时抛出
     * @since 1.0.0
     */
    Product selectById(Long id);

    /**
     * 按分类查询商品列表
     *
     * @param categoryId    一级分类ID（必须大于0）
     * @param subCategoryId 二级分类ID（可为null，表示不限制二级分类）
     * @return 商品列表（不会返回null，无结果时返回空集合）
     * @throws IllegalArgumentException 当categoryId为null或<=0时抛出
     * @apiNote 查询条件：
     * 1. 只返回状态为上架(status=1)的商品
     * 2. 当subCategoryId为null时只按一级分类查询
     * 3. 结果按create_time降序排序
     * @since 1.0.0
     */
    List<Product> selectByCategory(@Param("categoryId") Long categoryId,
                                   @Param("subCategoryId") Long subCategoryId);

    /**
     * 按商品名称模糊搜索
     *
     * @param keyword 搜索关键词（长度至少2个字符）
     * @param limit   返回记录数限制（可为null，表示不限制）
     * @return 匹配的商品列表（不会返回null，无结果时返回空集合）
     * @throws IllegalArgumentException 当：
     *                                  - keyword为null或长度<2
     *                                  - limit不为null且<=0时抛出
     * @apiNote 实现细节：
     * 1. 使用LIKE %keyword% 语法进行模糊匹配
     * 2. 只返回状态为上架(status=1)的商品
     * 3. 结果按create_time降序排序
     * @version 1.2.0 增加keyword长度校验
     * @since 1.0.0
     */
    List<Product> searchByName(@Param("keyword") String keyword,
                               @Param("limit") Integer limit);

    /**
     * 按分类分页查询商品列表
     *
     * @param categoryId    一级分类ID（必须传入，不可为null）
     * @param subCategoryId 二级分类ID（可选参数，可为null）
     * @param offset        分页偏移量（计算方式：pageNumber * pageSize）
     * @param size          每页记录数（必须大于0）
     * @return 分页商品列表（不会返回null，无数据时返回空集合）
     * @throws IllegalArgumentException 当size <= 0时抛出
     * @apiNote 查询逻辑说明：
     * 1. 只查询状态为上架(status=1)的商品
     * 2. 当subCategoryId为null时，只按一级分类查询
     * 3. 结果按创建时间降序排序(create_time DESC)
     * 4. 分页参数通过LIMIT offset, size实现
     * @version 1.1.0 新增subCategoryId可选参数支持
     * @since 1.0.0
     */
    List<Product> selectByCategoryWithPage(
            @Param("categoryId") Long categoryId,
            @Param("subCategoryId") Long subCategoryId,
            @Param("offset") int offset,
            @Param("size") int size);

    /**
     * 按分类统计商品数量
     *
     * @param categoryId    一级分类ID
     * @param subCategoryId 二级分类ID
     * @return 商品数量
     */
    long countByCategory(
            @Param("categoryId") Long categoryId,
            @Param("subCategoryId") Long subCategoryId);

    /**
     * 按商品名称分页模糊搜索商品列表
     *
     * @param keyword 搜索关键词（必须传入，长度至少2个字符）
     * @param offset  分页偏移量（计算方式：pageNumber * pageSize，必须 >= 0）
     * @param size    每页记录数（取值范围：1-1000）
     * @return 分页商品列表（不会返回null，无结果时返回空集合）
     * @throws IllegalArgumentException 当以下情况时抛出：
     *                                  - keyword长度小于2
     *                                  - offset < 0
     *                                  - size < 1 或 size > 1000
     * @apiNote 实现细节：
     * 1. 只查询状态为上架(status=1)的商品
     * 2. 使用LIKE进行模糊匹配，搜索字段为name
     * 3. 结果按创建时间降序排序(create_time DESC)
     * 4. 分页通过LIMIT offset, size实现
     * 5. 关键词前后自动添加通配符(%)实现包含匹配
     * @version 1.2.0 增加关键词长度校验
     * @since 1.0.0
     */
    List<Product> searchByNameWithPage(
            @Param("keyword") String keyword,
            @Param("offset") int offset,
            @Param("size") int size);

    /**
     * 按名称统计商品数量
     *
     * @param keyword 搜索关键词
     * @return 商品数量
     */
    long countByName(@Param("keyword") String keyword);
}
